<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
	<title>SoudnJS Example: Play With EaselJS</title>
	<link href="../_assets/css/shared.css" rel="stylesheet" type="text/css"/>
	<link href="../_assets/css/examples.css" rel="stylesheet" type="text/css"/>
	<link href="../_assets/css/soundjs.css" rel="stylesheet" type="text/css"/>
	<script src="../_assets/js/examples.js"></script>
</head>

<body onload="init();">
<!-- background isn't set to black to demonstrate how the darkening applies -->

<header class="SoundJS">
	<h1>Play with EaselJS</h1>

	<p>A simple demo demonstrating playing a lot of sounds at once while
		animating.
	</p>
</header>

<div id="error">
	<h2>Sorry!</h2>

	<p>SoundJS is not currently supported in your browser.</p>

	<p>Please <a href="http://github.com/CreateJS/SoundJS/issues" target="_blank">log a bug</a>
		with the device and browser you are using. Thank you.</p>
</div>

<div>
	<canvas id="testCanvas" width="960" height="400"></canvas>
</div>

<script type="text/javascript" src="../_assets/libs/easeljs-NEXT.min.js"></script>
<script type="text/javascript" src="../_assets/libs/preloadjs-NEXT.min.js"></script>
<script type="text/javascript" src="../lib/soundjs-NEXT.combined.js"></script>
<!-- We also provide hosted minified versions of all CreateJS libraries.
	http://code.createjs.com -->

<script id="editable">
	var canvas, stage;              // the canvas and stage we draw to
	var sparklePool = [];           // Sparkle object pool
	var h, w;                       // variables to store the width and height of the canvas
	var messageField;	        	// Message display field
	var sparkleShape;               // cached vector graphic instance
	var sparksPerClick = 100;       // Number of sparklers made per click.  This is a variable so we can adjust to lower performance mobile devices

	function init() {
		// set up our Sound to the default.  This will be WebAudioPlugin when available, otherwise HTMLAudioPlugin
		if (!createjs.Sound.initializeDefaultPlugins()) {
			document.getElementById("error").style.display = "block";
			document.getElementById("content").style.display = "none";
			return;
		}

		// if this is a mobile device, we reduce the number of sparkles per click for performance reasons
		if (createjs.BrowserDetect.isIOS || createjs.BrowserDetect.isAndroid || createjs.BrowserDetect.isBlackberry) {
			sparksPerClick = sparksPerClick >> 1;
		}

		// create a new stage and point it at our canvas:
		canvas = document.getElementById("testCanvas");
		stage = new createjs.Stage(canvas);

		// set the width and height we use in tick, so we only have to access this data once (quicker)
		h = canvas.height;
		w = canvas.width;

		// enable touch interactions if supported on the current device:
		createjs.Touch.enable(stage);

		// a message on our stage that we use to let the user know what is going on.  Useful when preloading.
		messageField = new createjs.Text("Loading", "bold 24px Arial", "#FFFFFF");
		messageField.maxWidth = 1000;
		messageField.textAlign = "center";  // NOTE this puts the registration point of the textField at the center
		messageField.x = canvas.width / 2;
		messageField.y = canvas.height / 2;
		stage.addChild(messageField);
		stage.update(); 	//update the stage to show text

		var soundInstanceLimit = sparksPerClick;    // set our limit of sound instances to allow for the bounce sound
		// check if we are using the HTMLAudioPlugin, and if so apply the MAX_INSTANCES to the above limit
		if (createjs.Sound.activePlugin.toString() == "[HTMLAudioPlugin]") {
			soundInstanceLimit = createjs.HTMLAudioPlugin.MAX_INSTANCES - 5;
		}

		// set up our manifest of assets to load
		var assetsPath = "../_assets/audio/";
		var manifest = [
			{src: "Game-Break.ogg", id: "0"},
			{src: "Game-Spawn.ogg", id: "1"},
			{src: "Game-Shot.ogg", id: "2"},
			{src: "Thunder1.ogg", id: "3"},
			{src: "Game-Death.ogg", id: "4"},
			{src: "GU-StealDaisy.ogg", id: "bounce", data: soundInstanceLimit}
		]

		// Instantiate a queue to preload our assets
		queue = new createjs.LoadQueue(true, assetsPath);
		createjs.Sound.alternateExtensions = ["mp3"];	// add other extensions to try loading if the src file extension is not supported
		queue.installPlugin(createjs.Sound);
		queue.addEventListener("complete", loadComplete);
		queue.addEventListener("error", handleFileError);
		queue.addEventListener("progress", handleProgress);
		queue.loadManifest(manifest);
	}

	// show progress so the user knows something is happening during preload
	function handleProgress(evt) {
		messageField.text += ".";
		stage.update();
	}

	function handleFileError(evt) {
		console.log("preload error ", evt.item.src);
		// An error occurred.
		messageField.text = "Error :("
		stage.update();
	}

	function loadComplete() {
		// we're ready, so we can remove the loading message
		stage.removeChild(messageField);

		// attach mouse handlers directly to the source canvas.
		// better than calling from canvas tag for cross browser compatibility:
		stage.addEventListener("stagemousemove", moveCanvas);
		stage.addEventListener("stagemousedown", clickCanvas);

		// create a semi-opaque black rectangle that covers the full stage.
		// drawing this to stage each tick will cause the canvas to fade to black.
		var shape = new createjs.Shape(new createjs.Graphics().beginFill('#333').drawRect(0, 0, canvas.width + 1, canvas.height));
		shape.alpha = 0.35;
		shape.cache(0, 0, canvas.width + 1, canvas.height);
		stage.addChild(shape);

		// create the cached shape we are building our sparkles out of, which makes rendering much quicker
		makeSparkle();

		// this prevents the stage from automatically clearing itself each tick.
		// in this demo, it results in the star trails, as the previous draws remain on screen.
		stage.autoClear = false;

		// start the tick and point it at the window so we can do some work before updating the stage:
		createjs.Ticker.addEventListener("tick", tick);
	}

	function tick() {
		// loop through all of the active sparkles on stage:
		var l = stage.getNumChildren();
		for (var i = l - 1; i > 0; i--) {
			var sparkle = stage.getChildAt(i);

			// apply gravity and friction
			sparkle.vY += 2;
			sparkle.vX *= 0.98;

			// update position, scale, and alpha:
			sparkle.x += sparkle.vX;
			sparkle.y += sparkle.vY;
			sparkle.alpha += sparkle.vA;

			// remove sparkles that are no longer visible or are stalled:
			if (sparkle.alpha <= 0 || sparkle.y >= h && sparkle.vY < 10) {
				stage.removeChildAt(i);
				sparklePool.push(sparkle);
				continue;
			}

			//bounce sparkles off the bottom
			if (sparkle.y > h) {
				sparkle.bounceSound.play();
				sparkle.vY *= -(Math.random() * 0.4 + 0.4);
				sparkle.y -= sparkle.y % h;
			}
			if (sparkle.x >= w || sparkle.x <= 0) {
				//sparkle.bounceSound.play();  // this was a bit too much
				sparkle.vX *= -1;
			}
		}

		// draw the updates to stage
		stage.update();
	}

	// sparkle explosion
	function clickCanvas(evt) {
		var id = Math.round(Math.random() * 4);  // random id that will match one of the id's used in the manifest of sounds, 0 to 4
		createjs.Sound.play(id.toString());
		addSparkles(Math.random() * sparksPerClick + sparksPerClick | 0, evt.stageX, evt.stageY, 2, 0);
	}

	//sparkle trail
	function moveCanvas(evt) {
		addSparkles(Math.random() * 2 + 1 | 0, evt.stageX, evt.stageY, 0.5, 0.5);
	}

	function addSparkles(count, x, y, speed, velX) {
		//create the specified number of sparkles
		for (var i = 0; i < count; i++) {
			// clone the original sparkle, so we don't need to set shared properties:
			var sparkle = getSparkle();

			// set display properties:
			sparkle.x = x;
			sparkle.y = y;
			sparkle.alpha = Math.random() * 0.5 + 0.5;
			sparkle.scaleX = sparkle.scaleY = Math.random() + 0.3;
			sparkle.rotation = Math.random() * 360;

			// set up velocities:
			var a = Math.PI * 2 * Math.random();
			var v = (Math.random() - 0.5) * 30 * speed;
			sparkle.vX = Math.cos(a) * v + velX;
			sparkle.vY = Math.sin(a) * v;
			sparkle.vA = -Math.random() * 0.05 - 0.01; // alpha

			// add to the display list:
			stage.addChild(sparkle);
		}
	}

	// object pool access function, this will either give us an existing object or create a new one
	// object pools are used to avoid the runtime cost of creating objects repeatedly, and the associated garbage collection cost (quicker)
	function getSparkle() {
		var s;
		if (this.sparklePool.length > 0) {
			// we have one in our pool, so lets remove it from the pool and return it
			s = this.sparklePool.pop();
		} else {
			// none in our pool, so we create the shape using our cached image (very fast)
			s = new createjs.Bitmap(sparkleShape.cacheCanvas);
			// add a bounce sound, which never changes after it's added
			s.bounceSound = createjs.Sound.createInstance("bounce");  // create it by id
			s.bounceSound.volume = (Math.random() * 0.01 + 0.01);  // because there will be a lot
		}
		return s;
	}

	// set up our cached instance that we use to draw new sparkles (quicker)
	function makeSparkle() {
		sparkleShape = new createjs.Shape();
		var g = sparkleShape.graphics;

		g.beginFill("#FFF");
		g.drawPolyStar(0, 0, 5, 5, 0.7, -90);
		g.endFill();

		// cache for faster redraws
		sparkleShape.cache(-3, -3, 10, 10);
	}
</script>

</body>
</html>
